from datetime import datetime
import pyflag.FlagFramework as FlagFramework
import pyflag.conf
config=pyflag.conf.ConfObject()
import pyflag.FileSystem as FileSystem
import pyflag.Reports as Reports
import pyflag.DB as DB
from pyflag.Scanner import *
import pyflag.Scanner as Scanner
from pyflag.ColumnTypes import StringType, InodeIDType, ColumnType, FilenameType, IntegerType, TimestampType, LongStringType, BinaryType
import pyflag.Reports as Reports
import os.path
import sqlite3
import re
import pyflag.pyflaglog as pyflaglog

class SkypeArchivesFoundCaseTable(FlagFramework.CaseTable):
    """ Found Skype archives table class. """
    # primary= "inode_id"
    name = 'skype_archives'
    columns = [
      [InodeIDType, {}],
      [StringType, {"name":"Path", "column":"path"}],
      [StringType, {"name":"Chatname", "column":"chatname"}],
      [StringType, {"name":"SkypeID", "column":"author"}],
      [LongStringType, {"name":"Chat body", "column":"body"}],
      [TimestampType, {"name":"Timestamp", "column":"timestamp"}],
    ]

class SkypeFinder(Reports.report):
    """ A report class for finding Skype archive files """
    name = "Show found Skype Archives"
    family = "Log Finder"
    description="The report returns a table of known Skype archive files."

    def form(self,query,result):
        result.case_selector()
        
    def display(self,query,result):
        dbh=self.DBO(query['case'])
        try:
            result.table(
                elements = [ 
                             FilenameType(case=query['case']),
                             StringType('Chatname', 'chatname'),
                             StringType('SkypeID', 'author'),
                             LongStringType(name='Chat', column='body'),
                             TimestampType(name='Timestamp', column='timestamp'),
                             ],
                table = 'skype_archives',
                case = query['case']
                )
        except DB.DBError,e:
            result.para("Error reading the Type table.")
            result.para("Error reported was:")
            result.text(e,style="red")

def is_skype_archive(filename):
    print "Processing %s" % (filename)
    conn = sqlite3.connect(os.path.abspath(filename))
    c = conn.cursor()
    try:
        query = c.execute("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND tbl_name IN ('Contacts', 'Messages', 'Chats')")
    except sqlite3.Error:
        return False
    row = query.fetchone()
    table_count = row[0]
    return table_count == 3

def iterate_skype_chats(filename):
    conn = sqlite3.connect(os.path.abspath(filename))
    query = """SELECT chatname, author, body_xml, timestamp
               FROM Messages
            """
    cursor = conn.cursor().execute(query)
    row = cursor.fetchone()
    while row:
        yield row
        row = cursor.fetchone()

class SkypeArchiveScan(GenScanFactory):
    """ Scan filesystem for Skype Archives """
    default = True
    depends = ['TypeScan']
    group = "FileScanners"
    order=400

    class Scan(BaseScanner):
        def finish(self):
            dbh=DB.DBO(self.case)
            pyflaglog.log(pyflaglog.INFO, "Processing %s as skype data" % self.fd.inode)

            template = "INSERT INTO skype_archives(inode_id, path, chatname, author, body, timestamp) values (%s, '%s', '%s', '%s', '%s', '%s')"
            # FIXME -- my low knowledge on python didn't let me import this class so I check it by "string"
            if self.fd.__class__.__name__ == "MountedFS_file" and is_skype_archive(self.fd.fd.name):
                for chatname, author, body, timestamp in iterate_skype_chats(self.fd.fd.name):
                    body_stripped = re.sub(r'<[^>]*?>', '', body)
                    sql = template % (self.inode_id, self.fd.fd.name, chatname, author, body_stripped, datetime.fromtimestamp(int(timestamp)))

                    dbh.execute(sql)
